using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;

using ChaseCameraSample;
using Tranquillity;
using TranquillityDemos;
using System.Diagnostics;

namespace Meteorite
{
    public class Ship : Entity
    {
        public bool Valid
        {
            get;
            set;
        }
        public int Lives{ get; set; }
        enum ShipViewType
        {
            eShipViewType_Enter,
            eShipViewType_Normal,
            eShipViewType_Out
        }

        FireParticleSystem fireParticleSystem;
        SmokePlumeEmitter smokePlumeEmitter;
        Meteorite game;
        Model ShieldModel;
        
        int nTick = 0;
        public Ship(Model model,Meteorite game)
            : base(model)
        {
            this.game = game;
            TouchPanel.EnabledGestures = GestureType.Tap | GestureType.FreeDrag;

            Texture2D fire = game.Content.Load<Texture2D>("particle/explosion");
            fireParticleSystem = new FireParticleSystem(500, fire);
            //fireParticleSystem.Enabled = false;
            //fireParticleSystem.EmissionRate = 250;
            smokePlumeEmitter = new SmokePlumeEmitter(Vector3.Zero, 0);
            smokePlumeEmitter.EmissionRate = 80;
            smokePlumeEmitter.Scale = 0.05f;
            fireParticleSystem.AddEmitter(smokePlumeEmitter);
            Meteorite.particleManager.AddParticleSystem(fireParticleSystem, BlendState.Additive);

            ShieldModel = game.Content.Load<Model>(GameConstant.MOdel_Shield);

            fireParticleSystem.Enabled = false;

            Scale = GameConstant.ShipScale;
        }

        public void Born()
        {
            Valid = true;
            fireParticleSystem.Enabled = true;
            Lives = GameConstant.ShipLives;
            velocity = Vector3.Zero;
            EnterState(ShipState.eState_Invincible_Flash);
        }


        public override void Update(GameTime gameTime)
        {
            if (!Valid)
            {
                return;
            }

            nTick++;
            FiniteMachine();

            //record force
            Vector3 lastForce = Force;
            base.Update(gameTime);
            //Debug.WriteLine("2----{0}", lastForce);
            //make some friction,so the ship will stop somehow
            float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
            if (0 == lastForce.X && 0!=velocity.X)
            {
                //V = F*T
                //float F = -Dir.X * GameConstant.Friction * Mass;
                //float VX = F/Mass*elapsed+velocity.X;

                Vector3 Dir = velocity;
                Dir.Normalize();
                if (0 != Dir.X)
                {
                    float VX = -Dir.X * GameConstant.Friction * elapsed + velocity.X;
                    if (VX * velocity.X < 0)
                    {
                        velocity.X = 0;
                    }
                    else
                    {
                        velocity.X = VX;
                    }
                }
            }

            if (0 == lastForce.Y && 0 != velocity.Y)
            {
                Vector3 Dir = velocity;
                Dir.Normalize();
                if (0 != Dir.Y)
                {
                    float VY = -Dir.Y * GameConstant.Friction * elapsed + velocity.Y;
                    if (VY * velocity.Y < 0)
                    {
                        velocity.Y = 0;
                    }
                    else
                    {
                        velocity.Y = VY;
                    }
                }
            }

            if (0 == lastForce.Z && 0 != velocity.Z)
            {
                Vector3 Dir = velocity;
                Dir.Normalize();
                if (0 != Dir.Z)
                {
                    float VZ = -Dir.Z * GameConstant.Friction * elapsed + velocity.Z;
                    if (VZ * velocity.Z < 0)
                    {
                        velocity.Z = 0;
                    }
                    else
                    {
                        velocity.Z = VZ;
                    }
                }
            }
           
            //Region limitation
            position.X = MathHelper.Clamp(position.X, GameConstant.SpaceLimit_Left, GameConstant.SpaceLimit_Right);
            position.Y = MathHelper.Clamp(position.Y, GameConstant.SpaceLimit_Down, GameConstant.SpaceLimit_Up);

            base.velocity.X = MathHelper.Clamp(base.Velocity.X, -GameConstant.MaxSpeed, GameConstant.MaxSpeed);
            base.velocity.Y = MathHelper.Clamp(base.Velocity.Y, -GameConstant.MaxSpeed, GameConstant.MaxSpeed);
            base.velocity.Z = MathHelper.Clamp(base.Velocity.Z, -GameConstant.MaxZSpeed, GameConstant.MaxZSpeed);

            //rotation by speed
            float Radion1 = -MathHelper.Clamp(MathHelper.PiOver4 * base.Velocity.X / GameConstant.MaxSpeed, -MathHelper.PiOver4, MathHelper.PiOver4);
            float Radion2 = MathHelper.Clamp(MathHelper.PiOver4 * base.Velocity.Y / GameConstant.MaxSpeed, -MathHelper.PiOver4, MathHelper.PiOver4);

            rotation.Z = Radion1;
            rotation.Y = Radion2;

            //Debug.WriteLine("{0},{1}", Rotation.Y, Rotation.Z);

            CalculateWorld();

            //Particle
            Vector3 p = Vector3.Transform(new Vector3(0, 15, 60), World);
            smokePlumeEmitter.Position = p;
            //smokePlumeEmitter.Velocity = -Velocity / 10;

            
        }


        public override void Draw(Matrix View, Matrix Projection)
        {
            if (!Valid)
            {
                fireParticleSystem.Enabled = false;
                return;
            }
            else
            {
                fireParticleSystem.Enabled = true;
            }

            switch (State)
            {
                case ShipState.eState_Invincible_Flash:
                    {
                        if (0 == nTick % 2)
                        {
                            fireParticleSystem.Enabled = true;
                            base.Draw(View, Projection);
                        }
                        else
                        {
                            fireParticleSystem.Enabled = false;
                        }
                    }
                    break;
                case ShipState.eState_Invincible_Shield:
                    {
                        fireParticleSystem.Enabled = true;
                        base.Draw(View, Projection);
                        {//Draw shield
                            Matrix[] transforms = new Matrix[ShieldModel.Bones.Count];
                            ShieldModel.CopyAbsoluteBoneTransformsTo(transforms);

                            foreach (ModelMesh mesh in model.Meshes)
                            {
                                foreach (BasicEffect effect in mesh.Effects)
                                {
                                    effect.EnableDefaultLighting();
                                    effect.World = transforms[mesh.ParentBone.Index] * World;

                                    effect.View = View;
                                    effect.Projection = Projection;
                                }
                                mesh.Draw();
                            }
                        }
                    }
                    break;
                case ShipState.eState_Speedup:
                case ShipState.eState_Normal:
                    {
                        fireParticleSystem.Enabled = true;
                        base.Draw(View, Projection);
                    }
                    break;
                    
            }
            
        }
        enum ShipState
        {
            eState_Invalid = 0,
            eState_Invincible_Flash,
            eState_Normal,
            eState_Invincible_Shield,
            eState_Speedup,
            eState_BeHit,
            eState_Die
        };

        ShipState State = ShipState.eState_Invalid;
        int StateCountdown = 0;

        private void EnterState(ShipState state)
        {
            switch (state)
            {
                case ShipState.eState_Invincible_Flash:
                    {
                        StateCountdown = 60;
                    }
                    break;
                case ShipState.eState_Normal:
                    {
                        StateCountdown = -1;
                    }
                    break;
                    
                case ShipState.eState_Invincible_Shield:
                    {
                        StateCountdown = -1;
                    }
                    break;
                case ShipState.eState_Speedup:
                    {
                        StateCountdown = 180;
                    }
                    break;
                case ShipState.eState_BeHit:
                    {
                        StateCountdown = 30;
                    }
                    break;
                case ShipState.eState_Die:
                    {
                        Valid = false;
                        fireParticleSystem.Enabled = false;
                        StateCountdown = 30;
                    }
                    break;
                case ShipState.eState_Invalid:
                default:
                    break;
            }

            State = state;
        }

        private void FiniteMachine()
        {
            if (StateCountdown > 0)
            {
                StateCountdown--;
            }

            switch (State)
            {
                case ShipState.eState_Invincible_Flash:
                    {
                        if (0 == StateCountdown)
                        {
                            EnterState(ShipState.eState_Normal);
                        }
                    }
                    break;
                case ShipState.eState_Invincible_Shield:
                    {
                        if (0 == StateCountdown)
                        {
                            EnterState(ShipState.eState_Normal);
                        }
                    }
                    break;
                case ShipState.eState_Speedup:
                    {
                        Force += Vector3.Forward * GameConstant.ThrustForce;
                        if (0 == StateCountdown)
                        {
                            EnterState(ShipState.eState_Normal);
                        }
                    }
                    break;
                case ShipState.eState_BeHit:
                    {
                        StateCountdown = 30;
                    }
                    break;
                case ShipState.eState_Die:
                    {
                        if (0 == StateCountdown)
                        {
                            EnterState(ShipState.eState_Invalid);
                        }
                    }
                    break;
                case ShipState.eState_Invalid:
                default:
                    break;
            }
        }

        public void SpeedUp()
        {
            EnterState(ShipState.eState_Speedup);
        }
        public void Shield()
        {
            EnterState(ShipState.eState_Invincible_Shield);
        }
        public bool RemoveShield()
        {
            if (ShipState.eState_Invincible_Shield==State)
            {
                EnterState(ShipState.eState_Normal);
                return true;
            }
            return false;
        }
        public void Demange()
        {
            if (CanBeHit() && ShipState.eState_Invincible_Shield == State)
            {
                 EnterState(ShipState.eState_Normal);
                 return;
            }

            Meteorite.camera.Shake(GameConstant.CameraExplosionCountDonw, 1, GameConstant.CameraExplosionRange);
            Lives--;
            UserData.Instance().AddValue(GameConstant.UserData_ColideStone, 1);
            if (Lives <= 0)
            {
                EnterState(ShipState.eState_Die);
                return;
            }
        }

        public bool CanBeHit()
        {
            if(!Valid)
            {
                return false;
            }
            if ( ShipState.eState_Invincible_Flash==State )
            {
                return false;
            }
            return true;
        }
        public bool CanEatSomething()
        {
            if (!Valid)
            {
                return false;
            }
            if (ShipState.eState_Invincible_Flash == State )
            {
                return false;
            }
            return true;
        }
    }
        
}
